// DIBImage.h: interface for the CDIBImage class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_DIBIMAGE_H__8A8C5813_22BF_4B7B_AAFB_F6EE364E56E7__INCLUDED_)
#define AFX_DIBIMAGE_H__8A8C5813_22BF_4B7B_AAFB_F6EE364E56E7__INCLUDED_

//////////////////////////// Includes /////////////////////////
#include "APIs/dibapi.h"
#include "../DS/Stack.h"
#include "WorkingArea/WorkingArea.h"
#include "UndoRedo/UndoNode.h"
#include "xImage.h"
#include "Colors/ColorConverter.h"
#include "Colors/ColorManager.h"

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

class CDIBImage;

// the DIB image's class ( entity class )
class CDIBImage : public CxImage
{
public:
	CDIBImage();				// the construction function
	virtual ~CDIBImage();
	BOOL Attach(HGLOBAL hGlobal);	// attach the handle of dib to the image
	void Destroy();					// destroy the current object's members

	CxImage* Copy();
	void Copy(CxImage *image) {}
	RGBQUAD** CopyTo2DArray() { return NULL; }

	BOOL IsGrayScaled() { return m_bGrayscaled || m_bBinarized;	}
	void SetGrayScaled(BOOL value) { m_bGrayscaled = value; }
	BOOL IsBinarized() { return m_bBinarized; }
	void SetBinarized(BOOL value) { m_bBinarized = value; }

	// create a dib image with the size and specified bit counts
	BOOL Create(CSize size, int nBPP);
	BOOL Create(int nWidth, int nHeight, int nBPP, DWORD dwFlags = 0);

	// load the image with specified lpszPathName
	HRESULT Load(LPCTSTR lpszPathName);
	HRESULT Load(HINSTANCE hInst, LPCTSTR lpResourceName);
	HRESULT Load(HINSTANCE hInst, UINT uID)
	{ return Load(hInst, MAKEINTRESOURCE(uID)); };

	// save the current object as a image to the specified lpszPathName
	HRESULT Save(LPCTSTR lpszPathName, REFGUID guidFileType= GUID_NULL);

	// draw the current object's image on the screen
	BOOL Draw(CDC &hDestDC, const RECT& rectDest, const RECT& rectSrc);
	BOOL Draw(CDC& dc, const CRect& rcDst, const CRect& rcSrc, CPalette* pPal=NULL);

	////////////////////////////////////////////////////////////////////////////////////////
	// copy the current working area to the clipboard
	BOOL CopyToClipboard();
	// paste the image to the current object from the clipboard
	BOOL PasteFromClipboard();
	// judge whether there's image in the clipboard for pasting
	BOOL PasteAvailable();

	// set the undo stack's size
	void SetUndoSize(UINT nUndoSize);

	// get the undo stack's size
	int UndoSize() const 
	{ return m_nUndoSize; };

	// save the current image's state and description into the undo stack
	BOOL SaveState(const CString& sDescription);
	BOOL SaveState(UINT nID);		// convert the ID to decription string

	// judge whether the current undo stack's empty
	BOOL UndoAvailable();
	// judge whether the current redo stack's empty
	BOOL RedoAvailable();
	// undo the operation
	BOOL Undo();
	// redo the operation
	BOOL Redo();
	
	CString UndoDescription() const;	// get the undo node's description
	CString RedoDescription() const;	// get the redo node's description

	CWorkingArea* GetWorkingArea();		// get the current woring area
	// set the working area
	void  SetWorkingArea(CWorkingArea* pWorkingArea);

	// get the current image's handle
	HDIB GetHDIB() const 
	{ return m_hDib; };
	// get the current image's palette
	HPALETTE GetHPALLETTE() const 
	{ return m_Pal; };

	// get the current image's rectangle
	CRect GetRect()
	{ return CRect(CPoint(0, 0), GetSize()); };
	// get the current image's size
	CSize GetSize()	
	{ return CSize(m_nWidth, m_nHeight); };
	// get the current image's width
	int GetWidth()
	{ return m_nWidth; };
	// get the current image's height
	int GetHeight()
	{ return m_nHeight; };
	// get the current image's scan width
	int ScanWidth() const     
	{ return m_nScanWidth; };
	// get the num of bits per pixel
	int BitsPerPixel() const  
	{ return m_nBitsPerPixel; };

	BOOL ResetIteration() { return TRUE; }
	BOOL SetNextPixelColor(const RGBQUAD& value) { return TRUE; }
	BOOL GetNextPixelColor(RGBQUAD& value) { return TRUE; }

	BOOL GetCurrentPixel(RGBQUAD& value) { return TRUE; }
	BOOL SetCurrentPixel(const RGBQUAD& value) { return TRUE; }

	int GetCurrentX() { return 1; }
	int GetCurrentY() { return 1; }

	BOOL SetPixelinBuffer(int x, int y, const RGBQUAD& value);
	BOOL SetPixelinBuffer(int x, int y, const COLORREF& value) { return TRUE; }
	BOOL GetPixelinBuffer(int x, int y, RGBQUAD& value);
	BOOL GetPixelinBuffer(int x, int y, COLORREF& value) { return TRUE; }
	
	// get the color of the point(x, y)'s pixel
	BOOL GetPixelA(int x, int y, COLORREF& value, LPSTR lpDibBits = NULL);
	// set the color of the point(x, y)'s pixel
	BOOL SetPixelA(int x, int y, const COLORREF& value, LPSTR lpDibBits = NULL);

	void* GetPixelAddress(int x, int y) { return NULL; }

	// the copy construction function
	CDIBImage(const CDIBImage& ds);

	// the == construciton function
	CDIBImage& operator=(const CDIBImage& ds);
	// copy the selected part of image to dib
	BOOL CopySelection(CDIBImage& dib);

	// get the histogram value for the image
	void GetHistograms(UINT* average, UINT* red, UINT* green, UINT *blue) {}
	UINT* GetAverageHistogram();
	UINT* GetRHistogram();
	UINT* GetGHistogram();
	UINT* GetBHistogram();

	// mirror the selected working area of the image
	BOOL Mirror();
	// fill a close area from the point with the color "brushColor"
	BOOL Fill(CPoint point, COLORREF brushColor);

	void *GetColorConverter() { return NULL; }
	void *GetColorManager() { return NULL; }

public:
	void InitColorTable() {}
	RGBQUAD* GetColorTable() { return NULL; }
	int GetMaxColorTableEntries() const { return 1; }

	// return the color of the point(x, y)
	COLORREF GetPixelColor(int x, int y, LPSTR lpDibBits = NULL);
	
	// clear the current working area with white color
	BOOL Clear ();
	// cancel the selected working area
	void CancelWorkingArea();
	// get the lpDibBits num
	LPSTR GetLPDibBits();
	// paste the image in the clipboard to the image dib with specified rect
	BOOL PasteFromDIBImage(CDIBImage &dib, CRect &rect);
	// convert the bitmap hBitmap to the Dibimage
	static HDIB BitmapToDIB(HBITMAP hBitmap, HPALETTE hPal);
	// compute the size of the current color palette
	int ComputePaletteSize(DWORD nBitCount);
	// the the num of bits per pixel of the image
	int GetBPP();

	BOOL		  m_bGrayscaled;
	BOOL		  m_bBinarized;
	HDIB          m_hDib;		// the handle of the dib image
	HPALETTE      m_Pal;		// the handle of the palette
	int           m_nWidth;		// the width of the image
	int           m_nHeight;	// the height of the image
	int           m_nUndoSize;	// the undo stack size
	int           m_nScanWidth;	// the scan width
	int           m_nBitsPerPixel;	// the num of bits per pxiel
	CWorkingArea* m_pWorkingArea;	// the working area

	// the undo stack
	CArray<CDibUndoNode*, CDibUndoNode*&> m_UndoStack;
	// the redo stack
	CArray<CDibUndoNode*, CDibUndoNode*&> m_RedoStack;
	// the current undo node's description
	CString m_sCurrentDescription;
protected:
	// clear the current redo stack
	void ClearRedoStack();
};

#endif // !defined(AFX_DIBIMAGE_H__8A8C5813_22BF_4B7B_AAFB_F6EE364E56E7__INCLUDED_)
